#include "AS3.h"
#include <assert.h>
#include "macros.h"
#include "buf.h"
#include "lexer.h"
#include "bson.h"

static AS3_Val referent;
static buf_t buf;
static buf_t out;
static buf_t err;

static AS3_Val
compile(unused void *self, AS3_Val args) {
  char *buffer;
  int length;
  AS3_Val ref;
  size_t len;
  int result;
  AS3_Val addr, error;

  AS3_ArrayValue(args, "StrType,IntType,AS3ValType", &buffer, &length, &ref);
  len = strlen(buffer + length) + length;
  buffer[len + 1] = '\0';
  buf_acquire(&out);
  buf_acquire(&err);
  result = bson_compile_buffer(buffer, len + 2, &buf, &out, &err);
  free(buffer);
  switch (result) {
  case 0:
    addr = AS3_Ptr((char *) buf_elems(&out));
    AS3_Set(ref, referent, addr);
    AS3_Release(addr);
    break;
  case 1:
  case 2:
    error = AS3_StringN(buf_elems(&err), buf_size(&err));
    AS3_Set(ref, referent, error);
    AS3_Release(error);
    break;
  default:
    assert(0);
  }
  buf_release(&err);
  AS3_Release(ref);
  return AS3_Int(result);
}

static AS3_Val
release(unused void *self, unused AS3_Val args) {
  buf_release(&out);
  return NULL;
}

int
main(void) {
  AS3_Val compileFunction, releaseFunction, lib;

  referent = AS3_String("referent");
  compileFunction = AS3_Function(NULL, compile);
  releaseFunction = AS3_Function(NULL, release);
  lib = AS3_Object("compile:AS3ValType,release:AS3ValType",
                   compileFunction, releaseFunction);
  AS3_Release(releaseFunction);
  AS3_Release(compileFunction);
  AS3_LibInit(lib);
  return 0;
}
